package uk.co.fullerlee.vicoid20.widget;


import emulator.cbm.basic.BasicHelper;
import uk.co.fullerlee.vicoid20.Vicoid20Main;
import uk.co.fullerlee.vicoid20.Vicoid20Thread;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class Vicoid20ScreenView extends SurfaceView implements SurfaceHolder.Callback {

	public Vicoid20Thread thread;
	private Vicoid20Main vicoid20Main;
	public boolean gameEnd;
	
	public void finish() {
		Log.d(Vicoid20Main.LOGTAG, "Finish called on Vicoid20ScreenView");
		thread.setRunning(false);
		vicoid20Main.finish();
		vicoid20Main = null;
		thread = null;
		System.gc();
	}
	
	public boolean onTouchEvent(MotionEvent me) {
		if (thread != null) {
			return thread.onTouchEvent(me);
		}
		else return false;
	}
	
	
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		Log.d(Vicoid20Main.LOGTAG, "Key down event: " + (char)event.getUnicodeChar());
		
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			//Swallow this event so that the back button onKeyUp can be handled
			return true;
		}
		
		return super.onKeyDown(keyCode, event);
	}

	private void putKey(char key) {
		String buf = new String();
		buf += key;
		BasicHelper.enterText(buf);
	} 
	
	@Override
	public boolean onKeyUp(int keyCode, KeyEvent event) {
		Log.d(Vicoid20Main.LOGTAG, "Key up event: " + (char)event.getUnicodeChar());
		
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			Log.d(Vicoid20Main.LOGTAG, "Back button has been pressed.  Ending gracefully");
			finish();
			gameEnd = true;
			return true;
		}
		else {
			putKey((char)event.getUnicodeChar());
		}
		
		return super.onKeyUp(keyCode, event);
	}
	
	public Vicoid20ScreenView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		
		setFocusable(true); // make sure we get key events
		this.setFocusableInTouchMode(true);
		this.requestFocus();
	}
	
	public Vicoid20ScreenView(Context context, AttributeSet attrs) {
		super(context, attrs);

		// register our interest in hearing about changes to our surface
		SurfaceHolder holder = getHolder();
		holder.addCallback(this);

		createThread();
		 
		setFocusable(true); // make sure we get key events
		this.setFocusableInTouchMode(true);
		this.requestFocus();
	}

	private void createThread() {
		// create thread only; it's started in surfaceCreated()
		Log.d(Vicoid20Main.LOGTAG, "Creating thread...");
		thread = new Vicoid20Thread(getHolder(), this.getContext(), new Handler() {
			@Override
			public void handleMessage(Message m) {
				// mStatusText.setVisibility(m.getData().getInt("viz"));
				// mStatusText.setText(m.getData().getString("text"));
			}
		}, this);
	}


	/* Callback invoked when the surface dimensions change. */
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
		thread.setSurfaceSize(width, height);
	}

	/*
	 * Callback invoked when the Surface has been created and is ready to be
	 * used.
	 */
	public void surfaceCreated(SurfaceHolder holder) {
		// start the thread here so that we don't busy-wait in run()
		// waiting for the surface to be created
		
		if (thread == null) createThread();
		
		thread.setRunning(true);
		
		if (!thread.isAlive()) {
			Log.d(Vicoid20Main.LOGTAG, "Starting thread...");
			try {
				thread.start();
			}
			catch (Exception e) {
				Log.e(Vicoid20Main.LOGTAG, "Unable to start thread.", e);
			}
		}
	}

	/*
	 * Callback invoked when the Surface has been destroyed and must no longer
	 * be touched. WARNING: after this method returns, the Surface/Canvas must
	 * never be touched again!
	 */
	public void surfaceDestroyed(SurfaceHolder holder) {
		// we have to tell thread to shut down & wait for it to finish, or else
		// it might touch the Surface after we return and explode
		Log.d(Vicoid20Main.LOGTAG, "Surface Destroyed in WordingoGameView");
		boolean retry = true;
		if (thread != null) {
			thread.setRunning(false);
			while (retry) {
				try {
					thread.join();
					retry = false;
				} catch (InterruptedException e) {
				}
			}
			//TODO - Shouldn't really be finishing here.
			this.finish();
		}
	}

	public void setActivity(Vicoid20Main vicoid20Main) {
		this.vicoid20Main = vicoid20Main;
	}
	
}
